HAL HSEM Typical use cases for migration

This section provides information about the HAL HSEM Typical use cases for migration.

The HSEM semaphore take/release processes remain unchanged between HAL1 and HAL2.

However, the HAL2 introduces several naming and typing updates. For example, the semaphore identifiers are now defined as typed enumeration values such as HAL_HSEM_0 to HAL_HSEM_31, and the semaphore states are returned as typed enumeration values such as HAL_HSEM_RELEASED or HAL_HSEM_TAKEN.

Use case: Take/Release a semaphore

This use case shows how the application take a semaphore before accessing a shared resource, then releases it once the processing is completed.

Sequence diagram

HAL1

HAL2

Take/Release a semaphore

@startuml
participant "User Application" as App
participant "HSEM Driver" as HSEM

group Take the hardware semaphore
App -> HSEM: HAL_HSEM_Take(HSEM_ID_0, process_id)
end
group Check semaphore state after take
App -> HSEM: HAL_HSEM_IsSemTaken(HSEM_ID_0)
HSEM --> App: 1U
note right of HSEM
The hardware semaphore is taken
end note
end

group Release the hardware semaphore
App -> HSEM: HAL_HSEM_Release(HSEM_ID_0, process_id)
end

group Check semaphore state after release
App -> HSEM: HAL_HSEM_IsSemTaken(HSEM_ID_0)
HSEM --> App: 0U
note right of HSEM
The hardware semaphore is released
end note
end
@enduml

Take/Release a semaphore

@startuml
participant "User Application" as App
participant "HSEM Driver" as HSEM

group Take the hardware semaphore
App -> HSEM: HAL_HSEM_Take(HAL_HSEM_0, process_id)
end
group Check semaphore state after take
App -> HSEM: HAL_HSEM_IsTaken(HAL_HSEM_0)
HSEM --> App: HAL_HSEM_TAKEN
note right of HSEM
The hardware semaphore is taken
end note
end

group Release the hardware semaphore
App -> HSEM: HAL_HSEM_Release(HAL_HSEM_0, process_id)
end

group Check semaphore state after release
App -> HSEM: HAL_HSEM_IsTaken(HAL_HSEM_0)
HSEM --> App: HAL_HSEM_RELEASED
note right of HSEM
The hardware semaphore is released
end note
end


@enduml

Code snippet

HAL1

HAL2

uint32_t sem_state;
#define HSEM_SEM_ID      (0U) /* HW semaphore 0*/

/* HSEM Clock Enable */
__HAL_RCC_HSEM_CLK_ENABLE() ;

HAL_HSEM_Take(HSEM_SEM_ID, 1U);

sem_state = HAL_HSEM_IsSemTaken(HSEM_SEM_ID);

if (sem_state == 1U)
{
   /* The hardware semaphore is taken */
}

HAL_HSEM_Release(HSEM_SEM_ID, 1U);

sem_state = HAL_HSEM_IsSemTaken(HSEM_SEM_ID);

if (sem_state == 0U)
{
   /* The hardware semaphore is released */
}
hal_hsem_status_t sem_state;


/* HSEM Clock Enable */
HAL_RCC_HSEM_EnableClock();

HAL_HSEM_Take(HAL_HSEM_0, 1U);

sem_state = HAL_HSEM_IsTaken(HAL_HSEM_0);

if (sem_state == HAL_HSEM_TAKEN)
{
      /* The hardware semaphore is taken */
}

HAL_HSEM_Release(HAL_HSEM_0, 1U);

sem_state = HAL_HSEM_IsTaken(HAL_HSEM_0);

if (sem_state == HAL_HSEM_RELEASED)
{
      /* The hardware semaphore is released */
}

Use case: FastTake/ReleaseAll all semaphores at once with correct Key

This use case shows how the application sets a clear key, takes multiple semaphores using the fast-take mechanism, then releases all semaphores associated with the current core in a single operation.

Sequence diagram

HAL1

HAL2

FastTake/ReleaseAll

@startuml
participant "User Application" as App
participant "HSEM Driver" as HSEM

group Set the clear key
    App -> HSEM: HAL_HSEM_SetClearKey(clear_key)
    note right of HSEM
        The semaphore clear key is configured
    end note
end
group Fast take the hardware semaphore 0
    App -> HSEM: HAL_HSEM_FastTake(HSEM_ID_0)
    note right of HSEM
        Hardware semaphore 0 is taken
    end note
end

group Fast take the hardware semaphore 1
    App -> HSEM: HAL_HSEM_FastTake(HSEM_ID_1)
    note right of HSEM
        Hardware semaphore 1 is taken
    end note
end

group get the clear key
    App -> HSEM: clear_key = HAL_HSEM_GetClearKey()
    HSEM --> App: <color:green>Return semaphore clear key App</color>
end


group Release all semaphores
    App -> HSEM: HAL_HSEM_ReleaseAll(clear_key, 1U)
    note right of HSEM
        All semaphores owned by the selected core
        are released in a single operation
    end note
end

group Check semaphore state after release all semaphores
App -> HSEM: HAL_HSEM_IsSemTaken(HSEM_ID_0)
HSEM --> App: 0U
App -> HSEM: HAL_HSEM_IsSemTaken(HSEM_ID_1)
HSEM --> App: 0U
note right of HSEM
The hardware semaphores are released
end note
end
@enduml

FastTake/ReleaseAll

@startuml

participant "User Application" as App
participant "HSEM Driver" as HSEM

group Set the clear key
    App -> HSEM: HAL_HSEM_SetClearKey(clear_key)
    note right of HSEM
        The semaphore clear key is configured
    end note
end

group Fast take the hardware semaphore 0
    App -> HSEM: HAL_HSEM_FastTake(HAL_HSEM_0)
    note right of HSEM
        Hardware semaphore 0 is taken
    end note
end

group Fast take the hardware semaphore 1
    App -> HSEM: HAL_HSEM_FastTake(HAL_HSEM_1)
    note right of HSEM
        Hardware semaphore 1 is taken
    end note
end

group get the clear key
    App -> HSEM: clear_key = HAL_HSEM_GetClearKey()
    HSEM --> App: <color:green>Return semaphore clear key App</color>
end

group Release all semaphores
    App -> HSEM: HAL_HSEM_ReleaseAll(clear_key, HAL_HSEM_LOCKID_CURRENT_CPU)
    note right of HSEM
        All semaphores owned by the current CPU
        are released in a single operation
    end note
end

group Check semaphore state after release
App -> HSEM: HAL_HSEM_IsTaken(HAL_HSEM_0)
HSEM --> App: HAL_HSEM_RELEASED
App -> HSEM: HAL_HSEM_IsTaken(HAL_HSEM_1)
HSEM --> App: HAL_HSEM_RELEASED
note right of HSEM
The hardware semaphores are released
end note
end

@enduml

Code snippet

HAL1

HAL2

uint32_t clear_key;
uint32_t sem_state0, sem_state1;
#define HSEM_ID_0 (0U) /* HW semaphore 0*/
#define HSEM_ID_1 (1U) /* HW semaphore 1*/

/* HW semaphore Clock enable */
__HAL_RCC_HSEM_CLK_ENABLE() ;

HAL_HSEM_SetClearKey(clear_key);

HAL_HSEM_FastTake(HSEM_ID_0);

HAL_HSEM_FastTake(HSEM_ID_1);

clear_key = HAL_HSEM_GetClearKey();

HAL_HSEM_ReleaseAll(clear_key, 1U);

sem_state0 = HAL_HSEM_IsSemTaken(HSEM_SEM_0);

sem_state1 = HAL_HSEM_IsSemTaken(HSEM_SEM_1);

if ((sem_state0 == 0U) && (sem_state1 == 0U))
{
   /* Both hardware semaphores are released */
}
uint32_t clear_key;
hal_hsem_status_t sem_state0, sem_state1;



/* HW semaphore Clock enable */
HAL_RCC_HSEM_EnableClock();

HAL_HSEM_SetClearKey(clear_key);

HAL_HSEM_FastTake(HAL_HSEM_0);

HAL_HSEM_FastTake(HAL_HSEM_1);

clear_key = HAL_HSEM_GetClearKey();

HAL_HSEM_ReleaseAll(clear_key, HAL_HSEM_LOCKID_CURRENT_CPU);

sem_state0 = HAL_HSEM_IsTaken(HAL_HSEM_0);

sem_state1 = HAL_HSEM_IsTaken(HAL_HSEM_1);

if ((sem_state0 == HAL_HSEM_RELEASED) && (sem_state1 == HAL_HSEM_RELEASED))
{
    /* Both hardware semaphores are released */
}

Use case: Synchronization between two processes

This use case shows how two processes synchronize on the same hardware semaphore. One process owns the semaphore first, while the second one waits for its release through interrupt notification.

Sequence diagram

Synchronization Between Two Processes

@startuml

participant "Process 1" as App1
participant "Process 2" as App2
participant "HSEM Driver" as HSEM
participant "NVIC" as NVIC
participant "HW" as HW

group Enable interruption
App2 -> HSEM: HAL_HSEM_ActivateNotification()
end

group Take the hardware semaphore
App1 -> HSEM: HAL_HSEM_Take()
note right of HSEM
The hardware semaphore is taken by Process 1
end note
end

group Release the hardware semaphore
App1 -> HSEM: HAL_HSEM_Release()
HW -> NVIC: Interrupt
NVIC -> HSEM: HAL_HSEM_IRQHandler()
HSEM --> App2: HAL_HSEM_FreeCallback()
note right of NVIC
The hardware semaphore is released
end note
end

group Disable interruption
App2 -> HSEM: HAL_HSEM_DeactivateNotification()
end

group Take the hardware semaphore
App2 -> HSEM: HAL_HSEM_Take()
note right of HSEM
The hardware semaphore is taken by User Process 2
end note
end

group Release the hardware semaphore
App2 -> HSEM: HAL_HSEM_Release()
end


@enduml

Code snippet

Process

HAL1

HAL2

Process 1

#define HSEM_PROCESS_1  12U
#define HSEM_ID  0U /* HW semaphore 0 */

/* HSEM Clock Enable */
__HAL_RCC_HSEM_CLK_ENABLE();

/* Take semaphore 0 with Process 1 */
HAL_HSEM_Take(HSEM_ID, HSEM_PROCESS_1);

/* Release semaphore 0 with Process 1 */
HAL_HSEM_Release(HSEM_ID, HSEM_PROCESS_1);
#define HSEM_PROCESS_1  12U


/* HSEM Clock Enable */
HAL_RCC_HSEM_EnableClock();

/* Take semaphore 0 with Process 1 */
HAL_HSEM_Take(HAL_HSEM_0, HSEM_PROCESS_1);

/* Release semaphore 0 with Process 1 */
HAL_HSEM_Release(HAL_HSEM_0, HSEM_PROCESS_1);

Process 2

#define HSEM_PROCESS_2  13U
#define HSEM_ID  0U /* HW semaphore 0 */
static volatile uint32_t hsem_released = 0U;

/* HSEM Clock Enable */
__HAL_RCC_HSEM_CLK_ENABLE();

/* Enable the interruption for semaphore 0 with Process 2 */
HAL_HSEM_ActivateNotification(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID));

/* Wait until the semaphore release is notified */
while (hsem_released == 0U)
{
}

/* Deactivate HSEM notification */
HAL_HSEM_DeactivateNotification(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID));

/* Take semaphore 0 with Process 2 */
HAL_HSEM_Take(HSEM_ID, HSEM_PROCESS_2);

/* Release semaphore 0 with Process 2 */
HAL_HSEM_Release(HSEM_ID, HSEM_PROCESS_2);

void HSEM_IRQHandler(void)
{
    HAL_HSEM_IRQHandler();
}

void HAL_HSEM_FreeCallback(uint32_t SemMask)
{
    if ((SemMask & __HAL_HSEM_SEMID_TO_MASK(HSEM_ID)) != 0U)
    {
        hsem_released = 1U;
    }
}
#define HSEM_PROCESS_2  13U
static volatile uint32_t hsem_released = 0U;


/* HSEM Clock Enable */
HAL_RCC_HSEM_EnableClock();

/* Enable the interruption for semaphore 0 with Process 2 */
HAL_HSEM_EnableFreeNotificationIT(HAL_HSEM_0);

/* Wait until the semaphore release is notified */
while (hsem_released == 0U)
{
}

/* Deactivate HSEM notification */
HAL_HSEM_DisableFreeNotificationIT(HAL_HSEM_0);

/* Take semaphore 0 with Process 2 */
HAL_HSEM_Take(HAL_HSEM_0, HSEM_PROCESS_2);

/* Release semaphore 0 with Process 2 */
HAL_HSEM_Release(HAL_HSEM_0, HSEM_PROCESS_2);

void HSEM_S_IRQHandler(void)
{
    HAL_HSEM_IRQHandler();
}

void HAL_HSEM_FreeCallback(hal_hsem_t semaphore)
{
    if (semaphore == HAL_HSEM_0)
    {
        hsem_released = 1U;
    }
}